package lab;

import java.util.Arrays;
import java.util.AbstractSet;
import java.util.Iterator;

/**
 * Class ClosedHashSet represents Set
 * Implemented add, contains, remove, size, isEmpty, toString, clear and iterator
 * @author Yan Gorbenko
 */

public class CloseHashSet extends AbstractSet<Integer> implements Iterable<Integer>{
	
	int NULL = Integer.MIN_VALUE;
	int size;
	int[] set;
	int f;

	/**
	 * @param size is the size structure
	 */
    public CloseHashSet(int size) {
        this.size = Math.max(3 * size / 2, size) + 1;
        set = new int [this.size];
        Arrays.fill(set, NULL);
	}

    /**
     * @param value the element to add
     * @return true if value add
     */
    boolean add(int value) {
    	for (int i = index(hash(value)); ; i++) {
    		if (i == size) i = 0;
    		if (set[i] == value) throw new IllegalArgumentException("Contains the same value");
            if (set[i] == NULL) {
            	set[i] = value; 
            	return true;
            }
    	}
	}
    
    /**
     * @param value the element to contains
     * @return false if value not contains and true if value contains
     */
    boolean contains(int value) {
    	for (int i = index(hash(value)); ; i++) {
    		if (i == size) i = 0;
            if (set[i] == NULL) return false;
            if (set[i] == value) return true;
        }
    }
    
    /**
     * @param value the element to remove
     * @return false if value not remove and true if value remove
     */
    boolean remove(int value){
    	for (int i = 0; i < size ; i++) {
            if (value == set[i]){
                    set[i] = NULL;
                    return true;
            }
    	}
    	return false;
    }
    
    /**
     * Gets iterator of this set and moves it into specified position.
     */
	@Override
	public Iterator<Integer> iterator() {
		return new MyIterator(0);
	}
	
	/**
	 * return is size structure
	 */
	@Override
	public int size() {
		f = 0;
    	for (int i = 0; i < size; i++) {
    		if(set[i] != NULL) f++;
    	}
    	return f;
	}
	
	/** 
	 * @return true if structure is empty and false if not empty
	 */
    boolean IsEmpty(){
    	for (int i = 0; i < size; i++) {
        	if(set[i] != NULL) return false;
        }
        return true;
    }
    
    /**
     * return string in which recorded values ​​structure
     */
    public String toString(){
    	String str = "";
    	for(int i = 0; i < size; i++) {
			if(set[i] != NULL) str = str + Integer.toString(set[i]) + " ";
		}
		return str;
	}
    
    /**
     * clear structure
     */
    public void clear(){
    	for (int i = 0; i < size; i++) {
    		set[i] = NULL;
    	}
    }
    
    /**
     * 
     * @param v is value
     */
    int hash(int v) {
    	return (v >> 15) ^ v;
    }
    
    /**
     * 
     * @param hash value
     */
	int index(int hash) {
		return Math.abs(hash) % size;
	}
	
	/**
	 * MyIterator is a data structure for moving through a Set
	 */
	class MyIterator implements Iterator<Integer> {
		
		int current = 0;
		
		/**
		 * @param start is starting position
		 */
		public MyIterator(int start) {
			current = start - 1;
			current = SeekNext();
		}
		
		/**
		 * looking for the next item
		 */
		private int SeekNext() {
			for (int i = current+1; i < size; i++) {
				if (set[i] != NULL) {
					return i;
				}
			}
			return -1;
		}
		
		/**
		 * Clears the current position
		 */
		@Override
		public void remove() {
			set[current] = NULL;
		}
		
		/**
		 * returns and moves to the next element
		 */
		@Override
		public Integer next() {
			int result = set[current];
			current = SeekNext();
			return result;
		}
		
		/**
		 * @return true if current position of iterator has next value; false otherwise.
		 */
		@Override
		public boolean hasNext() {
			return current != -1;
		}
	};
}